#pragma once

#include <string>
#include <deque>
#include <map>
#include <memory>
#include <atomic>
#include "../GrpcModule/GrpcModule.grpc.pb.h"
#include "../DataModule/HanaData.h"
#include "../Config/Vault.h"
#include "../Base/CriticalSection.h"
#include "Config.h"
#include "SyncDataCache.h"
#include "EnclaveProvider.h"
#include "SyncDataThread.h"
#include "SyncWriteDataThread.h"
#include "../Base/Event.h"

class SyncData
{
public:
	struct Task
	{
		std::string table_;
		int start_;
		int end_;
	};

    SyncData(std::shared_ptr<EnclaveProvider> &enclave_provider, Config *config);
    virtual ~SyncData();

	void generatorTask(HanaData &hana, std::vector<std::string> &tables, enclave::SyncTablesDatas &sync_tables_datas, enclave::SyncTablesDatas &sync_info_request);

	void syncData(const std::string &sync_id, Vault &vault, std::shared_ptr<EnclaveProvider> &enclave_provider);

	bool getTask(Task &task);

    void onNotifySync(const ::enclave::SyncNotifyRequest *request, ::enclave::SyncTablesDatas *response);

    void onSyncInfo(const ::enclave::SyncTablesDatas* request);

	void addSyncDatas(std::shared_ptr <enclave::SyncTableRows> sync_table_rows);

	bool popupSyncDatas(std::shared_ptr <enclave::SyncTableRows> &sync_table_rows);

	int popupSyncDatasSize();

	bool is_sync_finished() { return is_sync_finished_; }

	void setSyncFinished(bool finished);

public:
    static std::map<std::string, std::shared_ptr<SyncData>> sync_datas_map;

	std::vector<Task> tasks_;

    std::map<std::string, std::vector<Field>> tables_columns_;

	Event event_;

public:
    std::shared_ptr<EnclaveProvider> enclave_provider_;
    Config *config_;
	SyncDataCache sync_data_cache_;

private:
	std::atomic_bool is_sync_finished_ = false;
	
	std::atomic_int task_index_ = 0;
    std::vector<std::shared_ptr<SyncDataThread>> sync_data_threads_;

	CriticalSection sync_datas_cs_;
	std::deque<std::shared_ptr<enclave::SyncTableRows>> sync_datas_;

	std::vector<std::shared_ptr<SyncWriteDataThread>> sync_write_data_threads_;
};

